
package com.cqrcb.cloud.controller;


import com.alibaba.fastjson.JSON;
import com.cqrcb.cloud.config.annotation.CustomChain;
import com.cqrcb.cloud.config.annotation.CustomLogAnnotation;
import com.cqrcb.cloud.config.annotation.CustomValidation;
import com.cqrcb.cloud.config.redis.annotation.CustomCacheable;
import com.cqrcb.cloud.config.redis.template.RedisRepository;
import com.cqrcb.cloud.entity.Test;
import com.cqrcb.cloud.entity.api.req.Q;
import com.cqrcb.cloud.entity.api.res.ER;
import com.cqrcb.cloud.entity.api.res.R;
import com.cqrcb.cloud.entity.exception.CustomException;
import com.cqrcb.cloud.entity.exception.ExceptionMember;
import com.cqrcb.cloud.entity.quota.MultiQuotaCtrlMarketMain;
import com.cqrcb.cloud.entity.quota.io.MultiQuotaCtrlMarketMainIO;
import com.cqrcb.cloud.service.quota.MultiQuotaCtrlMarketMainService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.implementation.bytecode.Throw;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.data.redis.connection.stream.MapRecord;
import org.springframework.data.redis.connection.stream.RecordId;
import org.springframework.data.redis.connection.stream.StreamRecords;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;


/**
 * @author yangxueyong
 */
@CustomChain(currentName = "test")
@Slf4j
@RestController
public class TestController  implements ApplicationContextAware {

    @Autowired
    private MultiQuotaCtrlMarketMainService multiQuotaCtrlMarketMainService;

	@Autowired
	public RedisTemplate<String,String> redisTemplate;

	@CustomLogAnnotation
	@PostMapping("/test11")
	public R test11() {
		log.info("这是什么-->>>");
		if(1 == 1) {
			throw new CustomException(ExceptionMember.CUSTOMUSER_NOT_QUOTA_NULL_ERROR);
		}
		return R.data("ok_R");
	}

	@CustomValidation
	@CustomLogAnnotation
	@PostMapping("/test23")
	public R test23(@RequestBody Q<Test> q) {
		log.info("q->", JSON.toJSONString(q));
		return R.data("ok_R");
	}

	@CustomValidation
	@CustomLogAnnotation
	@PostMapping("/test88")
	public R test88(@RequestBody Q<Test> q) {
		Map map = new HashMap();
		map.put("name", JSON.toJSONString(q));
		map.put("age", "23");

		String s = JSON.toJSONString(map);
		// 项流key中添加消息
		RecordId id = redisTemplate.opsForStream().add("mq", map);

		for (int  x = 0 ;x < 100;x ++) {
			RecordId recordId = redisTemplate.opsForStream().add(MapRecord.create("channel", Collections.singletonMap("message", x + "")));
		}

		return R.data("ok_R");
	}

	@CustomValidation
	@CustomLogAnnotation
	@PostMapping("/test99/{id}")
	@CustomCacheable(value = "red",key = "#id",express = "#id=='1'")
	public String  test99(@PathVariable("id") String id) {
		return "99";
	}



	@CustomLogAnnotation
	@PostMapping("/cc")
	public R cc() {
		log.info("这是什么-->>>");
		long start = System.currentTimeMillis();
		int coreThead = 1000;
		ExecutorService executorService = Executors.newFixedThreadPool(coreThead);
		CountDownLatch cd = new CountDownLatch(coreThead);
		for (int i = 0; i < coreThead; i++) {
			executorService.submit(()->{
				long start1 = System.currentTimeMillis();
				while(true) {
					try {
						String x_hb = redisTemplate.opsForSet().pop("x_hb");
						if(x_hb == null){
							break;
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				long end1 = System.currentTimeMillis();
				System.out.println("当前线程->" + Thread.currentThread().getName() + ",耗时:" + (end1 - start1));
				cd.countDown();
			});
		}
		try {
			cd.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		executorService.shutdown();
		long end = System.currentTimeMillis();
		System.out.println("总耗时->" + (end - start));
		return R.data("ok_R");
	}

	@CustomValidation
	@CustomLogAnnotation
	@PostMapping("/cc1")
	public R cc1() {
//		log.info("这是什么-->>>");
		String x_hb = redisTemplate.opsForSet().pop("x_hb");
		return R.data(x_hb);
	}

	@CustomLogAnnotation
	@PostMapping("/cc2")
	public R cc2() {
		int randomVal = getRandomVal(1, 50);
		Long x_hb = redisTemplate.opsForValue().increment("x_js", randomVal * -1);
		return R.data(x_hb);
	}

	private static int getRandomVal(int min, int max) {
		Random random = new Random();
//		System.out.println("min->" + min + ",,max->" + max);
//        if(min > max){
//            min = min^max;
//            max = min^max;
//            min = min^max;
//        }
		return random.nextInt(max - min + 1) + min;
	}


	@CustomChain(currentName = "test22")
	@CustomLogAnnotation
	@PostMapping("/test22")
	public ER test22() {
		log.info("这是什么-->>>");
//		int i = 1 / 0 ;
		if(1 == 1) {
			throw new CustomException(ExceptionMember.CUSTOMUSER_NOT_QUOTA_NULL_ERROR);
		}
		return ER.data("ok_ER");
	}


	@CustomChain(currentName = "deduction")
	@CustomValidation
	@CustomLogAnnotation
	@PostMapping("/deduction")
	public R deduction(@RequestBody  Q<MultiQuotaCtrlMarketMainIO> multiQuotaCtrlMarketMainVoQ) {
		log.info("这是什么-->>>");
		R r = multiQuotaCtrlMarketMainService.deductionFinancialProductQuota(multiQuotaCtrlMarketMainVoQ);
		return r;
	}

	@RequestMapping(value = "/redisTest", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
	@ResponseBody
	public Map<String,Object> redisTest(){
		redisTemplate.opsForValue().set("myKey", "myValue",10, TimeUnit.SECONDS);
		String myKey = redisTemplate.opsForValue().get("myKey");
		System.out.println(myKey);
		Map<String,Object> resultMap = new HashMap<String,Object>();
		resultMap.put("myKey",myKey);
		return resultMap;
	}


	@CustomValidation
	@CustomLogAnnotation
	@GetMapping("/deduction1")
	public String deduction1(@RequestBody Q<MultiQuotaCtrlMarketMainIO> multiQuotaCtrlMarketMainVoQ, MultiQuotaCtrlMarketMain multiQuotaCtrlMarketMain) {
		return "";
	}

	@CustomValidation
	@CustomLogAnnotation
	@GetMapping("/deduction2")
	public String deduction2(@RequestBody MultiQuotaCtrlMarketMainIO multiQuotaCtrlMarketMainVoQ, MultiQuotaCtrlMarketMain multiQuotaCtrlMarketMain) {
		return "";
	}

	@CustomValidation
	@CustomLogAnnotation
	@GetMapping("/deduction3")
	public String deduction3() {
		return "";
	}

	@CustomValidation
	@CustomLogAnnotation
	@GetMapping("/test")
	public String test() {
		log.info("test--->123213");
		log.error("测试错误");
		int i = 1 / 0 ;
		return "";
	}

	@CustomValidation
	@CustomLogAnnotation
	@GetMapping("/test2")
	public String test2() throws InterruptedException {
		log.info("test2-11->");
		Thread.sleep(100 * 1000);
		log.info("test2-22->");
		return "";
	}

	@CustomValidation
	@CustomLogAnnotation
	@GetMapping("/test3")
	public String test3() {
		new Thread(() -> {
			try {
				log.info("test3-11->");
				Thread.sleep(100 * 1000);
				log.info("test3-22->");
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}).start();
		return "success";
	}


	private ApplicationContext applicationContext;

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}

	@RequestMapping("/shutdownByCTX")
	public String shutdownByCTX(){
		ConfigurableApplicationContext ctx = (ConfigurableApplicationContext) applicationContext;
		ctx.close();
		System.exit(1);
		return "context is shutdown!!!";
	}


//	@CustomLogAnnotation
//	@GetMapping("/trylock")
//	public String trylock() {
//		multiQuotaCtrlMarketMainService.trylock();
//		return "provider-" ;
//	}

}
